﻿using System;
using System.IO;
using UnityEngine.Networking;

namespace Yoozoo.Modules.Download
{
    public class FileDownloadHandler : DownloadHandlerScript
    {
        FileStream stream;
        bool isCancel;

        DownloadInfo downloadInfo;

        public FileDownloadHandler(byte[] preallocatedBuffer) : base(preallocatedBuffer)
        {
        }

        public void SetDownloadInfo(DownloadInfo downloadInfo)
        {
            this.downloadInfo = downloadInfo;
        }

        public bool OpenOrCreateFile()
        {
            try
            {
                isCancel = false;
                // GC.Alloc 8.4kb
                stream = File.Open(downloadInfo.Path, FileMode.OpenOrCreate, FileAccess.Write);
                stream.Seek((long)downloadInfo.CurrentSize, SeekOrigin.Begin);
            }
            catch (Exception e)
            {
                downloadInfo.ErrorMessage = e.Message;
                return false;
            }
            return true;
        }

        protected override void ReceiveContentLengthHeader(ulong contentLength)
        {
            downloadInfo.TotalSize = contentLength;
            base.ReceiveContentLengthHeader(contentLength);
        }

        protected override bool ReceiveData(byte[] data, int dataLength)
        {
            if (data == null || dataLength == 0 || isCancel || stream == null)
            {
                downloadInfo.ErrorMessage = "data == null || dataLength == 0";
                return false;
            }

            if (isCancel || stream == null)
            {
                downloadInfo.ErrorMessage = "UserCancel";
                return false;
            }

            if (stream == null)
            {
                downloadInfo.ErrorMessage = "stream == null";
                return false;
            }

            try
            {
                stream.Write(data, 0, dataLength);
                downloadInfo.CurrentSize = (ulong)stream.Length;
            }
            catch (Exception e)
            {
                downloadInfo.ErrorMessage = e.Message;
                return false;
            }
            return true;
        }

        protected override void CompleteContent()
        {
            base.CompleteContent();
            CloseStream();
        }

        public void CloseStream()
        {
            // 磁盘满的情况下，这里也会抛IOException
            try
            {
                if (stream != null)
                {
                    stream.Close();
                    stream.Dispose();
                    stream = null;
                }
            }
            catch (Exception e)
            {
                downloadInfo.ErrorMessage = e.Message;
            }
        }

        public void Cancel()
        {
            isCancel = true;
        }

        public void Reset()
        {
            CloseStream();
            isCancel = false;
            downloadInfo = null;
        }
    }
}
